import { forEachValue } from '@/utils'
// 自定义vuex库
let MVue

class Store {
  constructor(options = {}) {
    // 缓存参数
    this._mutations = options.mutations
    this._actions = options.actions
    // commit和dispatch绑定this,尤其是dispatch,异步中使用this,基本是混乱的,需要提前绑定
    this.commit = this.commit.bind(this)
    this.dispatch = this.dispatch.bind(this)

    // 自定义getter逻辑,本质是使用vue中computed特性
    const computed = {}
    this.getters = {}
    this._getters = options.getters
    const getters = this._getters
    const that = this
    forEachValue(getters, (fn, key) => {
      // https://zhuanlan.zhihu.com/p/49579052
      // fn函数为computed函数进行操作,俗称高阶函数
      // 高阶函数是对其他函数进行操作的函数，操作可以是将它们作为参数，或者是返回它们
      computed[key] = function() {
        return fn(that.state)
      }
      Object.defineProperty(that.getters, key, {
        get: () => that._vm[key],
        enumerable: true // for local getters
      })
    })
    /* eslint-disable no-new */
    this._vm = new MVue({
      data: {
        $$state: options.state
      },
      computed
    })
  }

  get state() {
    return this._vm._data.$$state
  }

  set state(v) {
    console.error('no set')
  }

  commit(type, params) {
    const method = this._mutations[type]
    if (!method) {
      console.error('mutations method is unknow')
      return
    }
    console.log('method', method)
    method(this.state, params)
  }

  dispatch(type, payload) {
    console.log('dispatch222')
    const action = this._actions[type]
    if (!action) {
      console.error('dispatch action is unknow')
      return
    }
    action(this, payload)
  }
}

function install(Vue) {
  MVue = Vue
  console.log('mVue', MVue)

  Vue.mixin({
    beforeCreate () {
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store
      }
    }
  })
}

export default { Store, install }
